home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 22
/
Cream of the Crop 22.iso
/
doom
/
quake2.zip
/
TF1_2SRC.ZIP
/
QUAKE
/
FORTRESS
/
SOURCE
/
TFORTMAP.QC
< prev
next >
Wrap
Text File
|
1996-09-10
|
30KB
|
1,256 lines
/*
TeamFortress 1.2 - 7/9/96
Robin Walker, John Cook, Ian Caughley.
Functions handling TeamFortress Map Goal Entities
*/
// Prototypes
// Team Functions
void(float tno, float scoretoadd) TeamFortress_TeamIncreaseScore;
void(float all) TeamFortress_TeamShowScores;
float() TeamFortress_TeamGetWinner;
// AutoDetect entity
void() info_tfdetect;
// Functions to handle spawning
void() TF_PlaceItem;
void() TF_StartItem;
// TeamSpawnpoint Functions
void() info_player_teamspawn;
// Goal Functions
void() info_tfgoal;
void() tfgoal_touch;
void() tfgoal_activate;
void(entity Goal, entity AP, float addb) tfgoal_result;
void(entity Goal, entity AP, float addb) tfgoal_normal_result;
void(entity Goal, entity AP, float addb) tfgoal_timer_result;
void() tfgoal_respawn;
void() tfgoal_timer_tick;
void(entity Goal, entity AP) tfgoal_goal_group;
void() TeamFortress_CheckClassStats;
entity(float gno) tfgoal_findgoal;
// GoalItem Functions
void() item_tfgoal;
void() item_tfgoal_touch;
void(entity Item) tfgoalitem_drop;
void() tfgoalitem_remove;
void() tfgoalitem_checkgoalreturn;
void(entity Item, entity AP) tfgoalitem_GiveToAP;
void(entity Item, entity AP, float method) tfgoalitem_RemoveFromAP;
entity(float ino) tfgoal_finditem;
//=========================================================================
// AUTODETECT ENTITY FUNCTIONS
//=========================================================================
//=========================================================================
// Spawn the detection entity
void() info_tfdetect =
{
self.solid = SOLID_NOT;
setsize (self, '-16 -16 -24', '16 16 32');
};
//=========================================================================
// SPAWNING FUNCTIONS
//=========================================================================
//=========================================================================
// Place the Goal Item
void() TF_PlaceItem =
{
local float oldz;
self.flags = FL_ITEM; // make extra wide
self.movetype = MOVETYPE_TOSS;
self.velocity = '0 0 0';
self.oldorigin = self.origin; // So we can return it later
};
//=========================================================================
// Start the Goal Item
void() TF_StartItem =
{
self.nextthink = time + 0.2; // items start after other solids
self.think = TF_PlaceItem;
};
//=========================================================================
// Place the Goal
void() TF_PlaceGoal =
{
local float oldz;
if (!(self.goal_activation & TFGA_TIMER_GOAL))
{
self.touch = tfgoal_touch;
}
else
{
if (self.search_time <= 0)
{
dprint("Timer Goal with no search_time specified.\n");
remove(self);
}
// Set up the next Timer Tick
self.think = tfgoal_timer_tick;
self.nextthink = time + self.search_time;
}
self.flags = FL_ITEM; // make extra wide
self.movetype = MOVETYPE_NONE;
self.velocity = '0 0 0';
self.oldorigin = self.origin; // So we can return it later
};
//=========================================================================
// Start the Goal
void() TF_StartGoal =
{
self.nextthink = time + 0.2; // items start after other solids
self.think = TF_PlaceGoal;
};
//=========================================================================
// Spawnpoints for team games with FortressMap
void() info_player_teamspawn =
{
if ((self.spawnflags) && (self.team_no == 0))
self.team_no = self.spawnflags;
// find the highest team number
if (number_of_teams < self.team_no)
number_of_teams = self.team_no;
// Team spawnpoints must have a team associated with them
if (self.team_no <= 0)
{
dprint("no team_no associated with info_player_teamspawn\n");
remove(self);
}
};
//=========================================================================
// GOAL FUNCTIONS
//=========================================================================
//=========================================================================
// Spawn the goal entity
void() info_tfgoal =
{
self.solid = SOLID_TRIGGER;
self.goal_state = TFGS_INACTIVE;
setsize (self, '-16 -16 -24', '16 16 32');
TF_StartGoal ();
};
//=========================================================================
// Touch function for the goal entity
void() tfgoal_touch =
{
local string st;
if (other.classname != "player")
return;
// Fortressmap is off?
if (!(toggleflags & TFLAG_FORTRESSMAP))
return;
// If it's a Timer Goal, return
if (self.goal_activation & TFGA_TIMER_GOAL)
return;
// If it is not activated in by the player's touch, return
if (!(self.goal_activation & TFGA_TOUCH))
return;
// Attempt to activate it
tfgoal_activate();
};
//=========================================================================
// Last check before activation. self = goal, other = player who activated it
void() tfgoal_activate =
{
local entity te;
local string db;
// If a player of a specific team can only activate this
if (self.goal_activation & TFGA_TEAM)
{
if (self.team_no != other.team_no)
return;
}
// If a player of a specific class can only activate this
if (self.goal_activation & TFGA_CLASS)
{
if (self.playerclass != other.playerclass)
return;
}
// If this activation needs a GoalItem, make sure the player has it
if (self.goal_activation & TFGA_ITEM)
{
te = tfgoal_finditem(self.items_allowed);
if (te.owner != other)
return;
}
// It's all ok.
// Do the results, adding the bonuses
tfgoal_result(self, other, 1);
};
//=========================================================================
// Goal has been activated.
// addb : >0 if you want to add bonuses of the goal to the AP
void(entity Goal, entity AP, float addb) tfgoal_result =
{
// If it's a Timer Goal, call the Timer Goal activation
if (Goal.goal_activation & TFGA_TIMER_GOAL)
{
tfgoal_timer_result(Goal, AP, addb);
return;
}
// Otherwise, call the Normal Goal activation
tfgoal_normal_result(Goal, AP, addb);
};
//=========================================================================
// Normal Goal has been activated.
// addb : >0 if you want to add bonuses of the goal to the AP
void(entity Goal, entity AP, float addb) tfgoal_normal_result =
{
local entity te, oldself;
local string st;
local float winners;
// Is the goal already activated?
// This check is needed for goals which are being activated by other goals
if (Goal.goal_state == TFGS_ACTIVE)
return;
// Goal is now active
Goal.goal_state = TFGS_ACTIVE;
stuffcmd (AP, "bf\n");
// Display the message and increase the team score
if (Goal.netname)
bprint(Goal.netname);
if (Goal.message)
sprint(AP, Goal.message);
if (Goal.count > 0)
{
if (AP.team_no > 0)
{
TeamFortress_TeamIncreaseScore(AP.team_no, Goal.count);
// Display short team scores
TeamFortress_TeamShowScores(2);
}
}
// Apply Stats, only if told to
if (addb)
{
if (Goal.health > 0)
T_Heal(AP, Goal.health, 0);
if (Goal.health < 0)
T_Damage(AP, Goal, Goal, (0 - Goal.health));
AP.armortype = AP.armortype + Goal.armortype;
AP.armorvalue = AP.armorvalue + Goal.armorvalue;
AP.frags = AP.frags + Goal.frags;
AP.ammo_shells = AP.ammo_shells + Goal.ammo_shells;
AP.ammo_nails = AP.ammo_nails + Goal.ammo_nails;
AP.ammo_rockets = AP.ammo_rockets + Goal.ammo_rockets;
AP.ammo_cells = AP.ammo_cells + Goal.ammo_cells;
AP.ammo_medikit = AP.ammo_medikit + Goal.ammo_medikit;
AP.ammo_detpack = AP.ammo_detpack + Goal.ammo_detpack;
AP.no_grenades_1 = AP.no_grenades_1 + Goal.no_grenades_1;
AP.no_grenades_2 = AP.no_grenades_2 + Goal.no_grenades_2;
// Apply any powerups
if (Goal.invincible_finished > 0)
{
AP.items = AP.items | IT_INVULNERABILITY;
AP.invincible_time = 1;
AP.invincible_finished = time + Goal.invincible_finished;
}
if (Goal.invisible_finished > 0)
{
AP.items = AP.items | IT_INVISIBILITY;
AP.invisible_time = 1;
AP.invisible_finished = time + Goal.invisible_finished;
}
if (Goal.super_damage_finished > 0)
{
AP.items = AP.items | IT_QUAD;
AP.super_time = 1;
AP.super_damage_finished = time + Goal.super_damage_finished;
}
if (Goal.radsuit_finished > 0)
{
AP.items = AP.items | IT_SUIT;
AP.rad_time = 1;
AP.radsuit_finished = time + Goal.radsuit_finished;
}
// Now apply the Playerclass limitations & Redisplay Ammo counts
oldself = self;
self = AP;
TeamFortress_CheckClassStats();
W_SetCurrentAmmo ();
self = oldself;
}
// If there's a GoalItem for this goal, give it to the player
if (Goal.goal_result & TFGR_ITEM)
{
if (Goal.items != 0)
{
// Find the item
te = tfgoal_finditem(Goal.items);
if (te)
{
// Give it to the player
tfgoalitem_GiveToAP(te, AP);
}
}
else
{
// No item specified in .items. Print error.
bprint("Goal ");
st = ftos(Goal.goal_no);
bprint(st);
bprint(" has goal_result bit ");
st = ftos(TFGR_ITEM);
bprint(st);
bprint(" set, but no .items specified.\n");
}
}
// If this goal removes an item from the player, remove it
if (Goal.goal_result & TFGR_ITEM_REMOVE)
{
if (Goal.axhitme != 0)
{
te = find (world, classname, "item_tfgoal");
while (te)
{
if ((te.owner == AP) && (te.goal_no == Goal.axhitme))
{
// Remove it from the player
tfgoalitem_RemoveFromAP(te, AP, 1);
}
te = find(te, classname, "item_tfgoal");
}
}
else
{
// No item specified in .items. Print error.
bprint("Goal ");
st = ftos(Goal.goal_no);
bprint(st);
bprint(" has goal_result bit ");
st = ftos(TFGR_ITEM_REMOVE);
bprint(st);
bprint(" set, but no .axhitme specified.\n");
}
}
// Does this goal end the level?
if (Goal.goal_result & TFGR_ENDGAME)
{
// Display Long TeamScores to everyone
TeamFortress_TeamShowScores(1);
winners = TeamFortress_TeamGetWinner();
// Stop everyone
te = find (world, classname, "player");
while (te)
{
te.takedamage = 0;
te.movetype = MOVETYPE_NONE;
// Can't append strings for centerprint :(
if (winners == 1)
centerprint(te, "Team 1 wins!\n");
if (winners == 2)
centerprint(te, "Team 2 wins!\n");
if (winners == 3)
centerprint(te, "Team 3 wins!\n");
if (winners == 4)
centerprint(te, "Team 4 wins!\n");
te = find(te, classname, "player");
}
te = spawn();
te.nextthink = time + 5; // Allow 3 secs to read the scores
te.think = execute_changelevel;
remove(Goal);
return;
}
// Do Goal Group checking
tfgoal_goal_group(Goal, AP);
// If another goal should be activated, activate it
if (Goal.goal_result & TFGR_GOAL_ACTIVATE)
{
if (Goal.impulse != 0)
{
// Find the goal
te = tfgoal_findgoal(Goal.impulse);
if (te)
{
tfgoal_result(te, AP, (!(AP.goal_result & TFGR_NO_ACT_BONUS)));
}
}
else
{
// No goal specified in .impulse. Print error.
bprint("Goal ");
st = ftos(Goal.goal_no);
bprint(st);
bprint(" has goal_result bit ");
st = ftos(TFGR_GOAL_ACTIVATE);
bprint(st);
bprint(" set, but no .impulse specified.\n");
}
}
// If another goal should be removed, remove it
if (Goal.goal_result & TFGR_GOAL_REMOVE)
{
if (Goal.waitmin != 0)
{
// Find the goal
te = tfgoal_findgoal(Goal.waitmin);
if (te)
{
te.solid = SOLID_NOT;
te.goal_state = TFGS_REMOVED;
}
}
else
{
// No goal specified in .waitmin. Print error.
bprint("Goal ");
st = ftos(Goal.goal_no);
bprint(st);
bprint(" has goal_result bit ");
st = ftos(TFGR_GOAL_REMOVE);
bprint(st);
bprint(" set, but no .waitmin specified.\n");
}
}
// If another goal should be restored, restore it
if (Goal.goal_result & TFGR_GOAL_RESTORE)
{
if (Goal.waitmax != 0)
{
// Find the goal
te = tfgoal_findgoal(Goal.waitmax);
if (te)
{
if (te.goal_state == TFGS_REMOVED)
{
te.solid = SOLID_TRIGGER;
te.goal_state = TFGS_INACTIVE;
}
}
}
else
{
// No goal specified in .waitmax. Print error.
bprint("Goal ");
st = ftos(Goal.goal_no);
bprint(st);
bprint(" has goal_result bit ");
st = ftos(TFGR_GOAL_RESTORE);
bprint(st);
bprint(" set, but no .waitmax specified.\n");
}
}
// If another goal should be inactivated, inactivate it
if (Goal.goal_result & TFGR_GOAL_INACTIVATE)
{
if (Goal.distance != 0)
{
// Find the goal
te = tfgoal_findgoal(Goal.distance);
if (te)
{
if (te.goal_state == TFGS_ACTIVE)
{
te.solid = SOLID_TRIGGER;
te.goal_state = TFGS_INACTIVE;
}
}
}
else
{
// No goal specified in .waitmax. Print error.
bprint("Goal ");
st = ftos(Goal.goal_no);
bprint(st);
bprint(" has goal_result bit ");
st = ftos(TFGR_GOAL_INACTIVATE);
bprint(st);
bprint(" set, but no .distance specified.\n");
}
}
// Check status of respawn for this goal
// Single Activation, do nothing
if (Goal.goal_result & TFGR_SINGLE)
{
Goal.solid = SOLID_NOT;
return;
}
// Respawn Activation, set up respawn
if (Goal.goal_result & TFGR_RESPAWN)
{
Goal.solid = SOLID_NOT;
Goal.nextthink = time + Goal.wait;
Goal.think = tfgoal_respawn;
return;
}
// Otherwise, it's a Multiple Goal
Goal.goal_state = TFGS_INACTIVE;
};
//=========================================================================
// Timer Goal has been activated.
// addb : >0 if you want to add bonuses of the goal to the AP
// AP and addb are still passed in, since I'll add in the ability to
// use an AP shortly.
void(entity Goal, entity AP, float addb) tfgoal_timer_result =
{
local entity te, oldself;
local string st;
local float winners;
// Is the goal already activated?
// This check is needed for goals which are being activated by other goals
if (Goal.goal_state == TFGS_ACTIVE)
return;
// Goal is now active
Goal.goal_state = TFGS_ACTIVE;
// Display the message and increase the team score
if (Goal.netname)
bprint(Goal.netname);
// Does this goal end the level?
if (Goal.goal_result & TFGR_ENDGAME)
{
// Display Long TeamScores to everyone
TeamFortress_TeamShowScores(1);
winners = TeamFortress_TeamGetWinner();
// Stop everyone
te = find (world, classname, "player");
while (te)
{
te.takedamage = 0;
te.movetype = MOVETYPE_NONE;
// Can't append strings for centerprint :(
if (winners == 1)
centerprint(te, "Team 1 wins!\n");
if (winners == 2)
centerprint(te, "Team 2 wins!\n");
if (winners == 3)
centerprint(te, "Team 3 wins!\n");
if (winners == 4)
centerprint(te, "Team 4 wins!\n");
te = find(te, classname, "player");
}
te = spawn();
te.nextthink = time + 5; // Allow 3 secs to read the scores
te.think = execute_changelevel;
remove(Goal);
return;
}
// Do Goal Group checking
// No activations!
if (!(Goal.goal_group & TFGG_ACTIVATE))
tfgoal_goal_group(Goal, AP);
else
bprint("Timer Goal attempting to do Goal Group actions!\n");
// If another goal should be removed, remove it
if (Goal.goal_result & TFGR_GOAL_REMOVE)
{
if (Goal.waitmin != 0)
{
// Find the goal
te = tfgoal_findgoal(Goal.waitmin);
if (te)
{
te.solid = SOLID_NOT;
te.goal_state = TFGS_REMOVED;
}
}
else
{
// No goal specified in .waitmin. Print error.
bprint("Goal ");
st = ftos(Goal.goal_no);
bprint(st);
bprint(" has goal_result bit ");
st = ftos(TFGR_GOAL_REMOVE);
bprint(st);
bprint(" set, but no .waitmin specified.\n");
}
}
// If another goal should be restored, restore it
if (Goal.goal_result & TFGR_GOAL_RESTORE)
{
if (Goal.waitmax != 0)
{
// Find the goal
te = tfgoal_findgoal(Goal.waitmax);
if (te)
{
if (te.goal_state == TFGS_REMOVED)
{
te.solid = SOLID_TRIGGER;
te.goal_state = TFGS_INACTIVE;
}
}
}
else
{
// No goal specified in .waitmax. Print error.
bprint("Goal ");
st = ftos(Goal.goal_no);
bprint(st);
bprint(" has goal_result bit ");
st = ftos(TFGR_GOAL_RESTORE);
bprint(st);
bprint(" set, but no .waitmax specified.\n");
}
}
// If another goal should be inactivated, inactivate it
if (Goal.goal_result & TFGR_GOAL_INACTIVATE)
{
if (Goal.distance != 0)
{
// Find the goal
te = tfgoal_findgoal(Goal.distance);
if (te)
{
if (te.goal_state == TFGS_ACTIVE)
{
te.solid = SOLID_TRIGGER;
te.goal_state = TFGS_INACTIVE;
}
}
}
else
{
// No goal specified in .waitmax. Print error.
bprint("Goal ");
st = ftos(Goal.goal_no);
bprint(st);
bprint(" has goal_result bit ");
st = ftos(TFGR_GOAL_INACTIVATE);
bprint(st);
bprint(" set, but no .distance specified.\n");
}
}
// Set up the next Timer Tick
Goal.goal_state = TFGS_INACTIVE;
Goal.think = tfgoal_timer_tick;
Goal.nextthink = time + Goal.search_time;
};
//=========================================================================
// Respawn the goal
void() tfgoal_respawn =
{
if (self.goal_state != TFGS_REMOVED)
{
self.goal_state = TFGS_INACTIVE;
self.solid = SOLID_TRIGGER; // allow it to be touched again
}
};
//=========================================================================
// Activate the Timer goal
void() tfgoal_timer_tick =
{
if (self.goal_state != TFGS_REMOVED)
{
tfgoal_result(self, world, 0); // Do Timer Tick again
}
};
//=========================================================================
// Check and do any behaviour for the goal's group
void(entity Goal, entity AP) tfgoal_goal_group =
{
local string st;
local entity tg;
local float allset;
// Check all goals activated flag
if (Goal.goal_group & TFGG_ACTIVATE)
{
// Make sure a valid group no is specified
if (Goal.height == 0)
{
// No goal specified in .height. Print error.
bprint("Goal ");
st = ftos(Goal.goal_no);
bprint(st);
bprint(" has goal_group bit ");
st = ftos(TFGG_ACTIVATE);
bprint(st);
bprint(" set, but no .height specified.\n");
}
else if (Goal.last_impulse == 0)
{
// No goal specified in .lastimpulse. Print error.
bprint("Goal ");
st = ftos(Goal.goal_no);
bprint(st);
bprint(" has goal_group bit ");
st = ftos(TFGG_ACTIVATE);
bprint(st);
bprint(" set, but no .last_impulse specified.\n");
}
else
{
allset = 1;
// Find all goals
tg = find (world, classname, "info_tfgoal");
while (tg)
{
if (tg.group_no == Goal.height)
{
if (tg.goal_state != TFGS_ACTIVE)
allset = 0;
}
tg = find(tg, classname, "info_tfgoal");
}
// If all goals in this group are activated, do it
if (allset)
{
// Find the goal
tg = tfgoal_findgoal(Goal.last_impulse);
if (tg)
{
tfgoal_result(tg, AP, 0); // Don't apply bonuses
}
}
}
}
// Check Activate all in the group flag
if (Goal.goal_group & TFGG_ACTIVATE_ALL)
{
// Make sure a valid group no is specified
if (Goal.aflag == 0)
{
// No goal specified in .aflag. Print error.
bprint("Goal ");
st = ftos(Goal.goal_no);
bprint(st);
bprint(" has goal_group bit ");
st = ftos(TFGG_ACTIVATE_ALL);
bprint(st);
bprint(" set, but no .aflag specified.\n");
}
else
{
// Find all goals
tg = find (world, classname, "info_tfgoal");
while (tg)
{
if (tg.group_no == Goal.aflag)
{
tfgoal_result(tg, AP, 0); // Don't apply bonuses
}
tg = find(tg, classname, "info_tfgoal");
}
}
}
// Check Inactivate all in the group flag
if (Goal.goal_group & TFGG_INACTIVATE_ALL)
{
// Make sure a valid group no is specified
if (Goal.dmg == 0)
{
// No goal specified in .dmg. Print error.
bprint("Goal ");
st = ftos(Goal.goal_no);
bprint(st);
bprint(" has goal_group bit ");
st = ftos(TFGG_ACTIVATE_ALL);
bprint(st);
bprint(" set, but no .dmg specified.\n");
}
else
{
// Find all goals
tg = find (world, classname, "info_tfgoal");
while (tg)
{
if (tg.group_no == Goal.dmg)
{
if (tg.goal_state == TFGS_ACTIVE)
{
tg.goal_state = TFGS_INACTIVE;
tg.solid = SOLID_TRIGGER;
}
}
tg = find(tg, classname, "info_tfgoal");
}
}
}
// Check Remove all in the group flag
if (Goal.goal_group & TFGG_REMOVE_ALL)
{
// Make sure a valid group no is specified
if (Goal.cnt == 0)
{
// No goal specified in .cnt. Print error.
bprint("Goal ");
st = ftos(Goal.goal_no);
bprint(st);
bprint(" has goal_group bit ");
st = ftos(TFGG_ACTIVATE_ALL);
bprint(st);
bprint(" set, but no .cnt specified.\n");
}
else
{
// Find all goals
tg = find (world, classname, "info_tfgoal");
while (tg)
{
if (tg.group_no == Goal.cnt)
{
tg.goal_state = TFGS_REMOVED;
tg.solid = SOLID_NOT;
}
tg = find(tg, classname, "info_tfgoal");
}
}
}
// Check Restore all in the group flag
if (Goal.goal_group & TFGG_RESTORE_ALL)
{
// Make sure a valid group no is specified
if (Goal.pausetime == 0)
{
// No goal specified in .pausetime. Print error.
bprint("Goal ");
st = ftos(Goal.goal_no);
bprint(st);
bprint(" has goal_group bit ");
st = ftos(TFGG_ACTIVATE_ALL);
bprint(st);
bprint(" set, but no .pausetime specified.\n");
}
else
{
// Find all goals
tg = find (world, classname, "info_tfgoal");
while (tg)
{
if (tg.group_no == Goal.pausetime)
{
if (tg.goal_state == TFGS_REMOVED)
{
tg.goal_state = TFGS_INACTIVE;
tg.solid = SOLID_TRIGGER;
}
}
tg = find(tg, classname, "info_tfgoal");
}
}
}
};
//=========================================================================
// Return the goal with a goal_no equal to gno
entity(float gno) tfgoal_findgoal =
{
local entity tg;
local string st;
// Look for the goal
tg = find (world, classname, "info_tfgoal");
while (tg)
{
if (tg.goal_no == gno)
{
return tg;
}
tg = find(tg, classname, "info_tfgoal");
}
// Goal does not exist
bprint("Could not find a goal with a goal_no of ");
st = ftos(gno);
bprint(st);
bprint(".\n");
};
//=========================================================================
// GOALITEM FUNCTIONS
//=========================================================================
// Spawn the goalitem entity
void() item_tfgoal =
{
// Graphic
if (self.mdl)
{
precache_model2(self.mdl);
setmodel(self, self.mdl);
}
else
{
// Default mdl for a GoalItem that shouldn't be seen
self.mdl = "progs/w_s_key.mdl";
precache_model("progs/w_s_key.mdl");
setmodel(self, "progs/w_s_key.mdl");
}
// Respawn sound
precache_sound2("items/itembk2.wav");
// Collection sound
if (self.noise)
{
precache_sound2(self.noise);
}
else
{
// Default wav sound for a GoalItem collection
self.noise = "misc/basekey.wav";
precache_sound2("misc/basekey.wav");
}
self.touch = item_tfgoal_touch;
self.goal_state = TFGS_INACTIVE;
// Should this be placed on the map?
if (self.goal_activation & TFGI_NOEXIST)
{
self.solid = SOLID_NOT;
}
else
{
self.solid = SOLID_TRIGGER;
setmodel(self, self.mdl);
setorigin(self, self.origin);
}
if (!(self.netname))
self.netname = "goalitem";
if (self.delay <= 0)
self.delay = 120;
setsize (self, '-16 -16 -24', '16 16 32');
TF_StartItem ();
};
//=========================================================================
// Touch function for the goalitem entity
void() item_tfgoal_touch =
{
local string st;
local entity te;
if (other.classname != "player")
return;
// Fortressmap is off?
if (!(toggleflags & TFLAG_FORTRESSMAP))
return;
// If a player of a specific team can get this one
if (self.goal_activation & TFGI_TEAM)
{
if (self.team_no != other.team_no)
return;
}
// If a player must be of a particular class to get this one
if (self.goal_activation & TFGI_CLASS)
{
if (self.playerclass != other.playerclass)
return;
}
// If a player needs a GoalItem to be able to get this one
if (self.goal_activation & TFGI_ITEM)
{
te = tfgoal_finditem(self.items_allowed);
if (te.owner != other)
return;
}
// Give it to the player
tfgoalitem_GiveToAP(self, other);
};
//=========================================================================
// Return the item with a goal_no equal to ino
entity(float ino) tfgoal_finditem =
{
local entity tg;
local string st;
// Look for the goal
tg = find (world, classname, "item_tfgoal");
while (tg)
{
if (tg.goal_no == ino)
{
return tg;
}
tg = find(tg, classname, "item_tfgoal");
}
// Goal does not exist
bprint("Could not find an item with a goal_no of ");
st = ftos(ino);
bprint(st);
bprint(".\n");
};
//=========================================================================
// Give the GoalItem to a Player.
void(entity Item, entity AP) tfgoalitem_GiveToAP =
{
local string sp;
// Display the message
if (Item.message)
bprint(Item.message);
if (Item.deathtype)
sprint(AP, Item.deathtype);
// Make the sound
sound (other, CHAN_ITEM, Item.noise, 1, ATTN_NORM);
Item.owner = AP;
// Remove it from the map
Item.model = string_null;
Item.solid = SOLID_NOT;
// Don't let it return
Item.goal_state = TFGS_INACTIVE;
// Do the deeds on the player
if (Item.goal_activation & TFGI_GLOW)
AP.effects = AP.effects | EF_BRIGHTLIGHT;
if (Item.goal_activation & TFGI_SLOW)
{
AP.maxfbspeed = (AP.maxfbspeed / 2);
AP.maxstrafespeed = (AP.maxstrafespeed / 2);
sp = ftos(AP.maxfbspeed);
stuffcmd(AP,"cl_backspeed ");
stuffcmd(AP,sp);
stuffcmd(AP,"\n");
stuffcmd(AP,"cl_forwardspeed ");
stuffcmd(AP,sp);
stuffcmd(AP,"\n");
sp = ftos(AP.maxstrafespeed);
stuffcmd(AP,"cl_sidespeed ");
stuffcmd(AP,sp);
stuffcmd(AP,"\n");
}
};
//=========================================================================
// Remove the GoalItem from a Player. self = item, other = player
void(entity Item, entity AP, float method) tfgoalitem_RemoveFromAP =
{
local entity oldself;
// Remove the deeds from the player
AP.effects = AP.effects - (AP.effects & EF_BRIGHTLIGHT);
if (Item.goal_activation & TFGI_SLOW)
{
oldself = self;
self = AP;
TeamFortress_SetSpeed();
self = oldself;
}
// Return it to the starting point if the flag is set
if (method == 0) // Dropped by a dying player
{
// Drop it if the flag is set
if (Item.goal_activation & TFGI_DROP)
{
tfgoalitem_drop(Item);
}
else if (Item.goal_activation & TFGI_RETURN_DROP)
{
Item.solid = SOLID_TRIGGER;
Item.touch = item_tfgoal_touch;
Item.origin = Item.oldorigin;
setmodel(Item, Item.mdl);
setorigin(Item, Item.origin);
sound (Item, CHAN_VOICE, "items/itembk2.wav", 1, ATTN_NORM);
// Restore a goal if needed
tfgoalitem_checkgoalreturn();
}
else
{
// Remove the Item
remove(Item);
}
Item.owner = world;
return;
}
// Return it to the starting point if the flag is set
if (method == 1) // Removed by a goal activation
{
if (Item.goal_activation & TFGI_RETURN_GOAL)
{
Item.solid = SOLID_TRIGGER;
Item.touch = item_tfgoal_touch;
Item.origin = Item.oldorigin;
setmodel(Item, Item.mdl);
setorigin(Item, Item.origin);
sound (Item, CHAN_VOICE, "items/itembk2.wav", 1, ATTN_NORM);
// Restore a goal if needed
tfgoalitem_checkgoalreturn();
}
// Don't remove it anyway, since it may be given away again later
self.solid = SOLID_NOT;
Item.owner = world;
return;
}
};
//=========================================================================
// Drop the item just like a backpack
void(entity Item) tfgoalitem_drop =
{
Item.origin = Item.owner.origin - '0 0 24';
Item.velocity_z = 300;
Item.velocity_x = -100 + (random() * 200);
Item.velocity_y = -100 + (random() * 200);
Item.movetype = MOVETYPE_TOSS;
Item.solid = SOLID_TRIGGER;
Item.touch = item_tfgoal_touch;
setorigin(Item, Item.origin);
setmodel(Item, Item.mdl);
// If the flag is set, remove it after 2 minutes
if (Item.goal_activation & TFGI_REMOVE)
{
Item.goal_state = TFGS_ACTIVE;
Item.nextthink = time + Item.delay;
Item.think = tfgoalitem_remove;
}
};
//=========================================================================
// Remove the item, or Return it if needed
void() tfgoalitem_remove =
{
// Has someone picked it up?
if (self.goal_state != TFGS_ACTIVE)
return;
// Should it be returned?
if (self.goal_activation & TFGI_RETURN_REMOVE)
{
self.solid = SOLID_TRIGGER;
self.touch = item_tfgoal_touch;
self.origin = self.oldorigin;
setmodel(self, self.mdl);
setorigin (self, self.origin);
sound (self, CHAN_VOICE, "items/itembk2.wav", 1, ATTN_NORM);
// Restore a goal if needed
tfgoalitem_checkgoalreturn();
return;
}
remove(self);
};
//=========================================================================
// Restore a goal when this item is removed, if needed
void() tfgoalitem_checkgoalreturn =
{
local string st;
local entity te;
// Do we need to restore a goal somewhere?
if (self.goal_activation & TFGI_RESTORE_GOAL)
{
if (self.impulse != 0)
{
// Find the goal
te = tfgoal_findgoal(self.impulse);
if (te)
{
// Restore it
te.solid = SOLID_TRIGGER;
if (te.goal_state == TFGS_REMOVED)
te.goal_state = TFGS_INACTIVE;
}
}
else
{
// No goal specified in .impulse. Print error.
bprint("GoalItem ");
st = ftos(self.goal_no);
bprint(st);
bprint(" has goal_activation bit ");
st = ftos(TFGI_RESTORE_GOAL);
bprint(st);
bprint(" set, but no .impulse specified.\n");
}
}
};